import copyToClipboard from 'copy-to-clipboard'

export function countWord(data: string): number {
  const regexp
    = /[a-zA-Z0-9_\u0392-\u03c9\u00c0-\u00ff\u0600-\u06ff\u0400-\u04ff]+|[\u4e00-\u9fff\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af]+/g

  data = typeof data === 'string' ? data : JSON.stringify(data)
  const matches = data.match(regexp)
  let totalCount = 0
  if (!matches) {
    return 0
  }
  for (let i = 0; i < matches.length; i++) {
    if (matches[i].charCodeAt(0) >= 0x4e00) {
      totalCount += matches[i].length
    }
    else {
      totalCount += 1
    }
  }
  return totalCount
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function debounce<T extends (...args: any[]) => void>(
  fn: T,
  delay: number = 500,
): (...args: Parameters<T>) => void {
  let timer: ReturnType<typeof setTimeout> | null = null

  return function (...args: Parameters<T>): void {
    if (timer !== null) {
      clearTimeout(timer)
    }

    timer = setTimeout(() => {
      fn(...args)
    }, delay)
  }
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function throttle<T extends (...args: any[]) => void>(
  fn: T,
  delay: number = 500,
  options: { trailing?: boolean } = {},
): (...args: Parameters<T>) => void {
  let lastCall = 0
  let timeoutId: ReturnType<typeof setTimeout> | null = null
  const { trailing = true } = options

  return function (...args: Parameters<T>): void {
    const now = Date.now()
    const remaining = delay - (now - lastCall)

    if (remaining <= 0) {
      if (timeoutId) {
        clearTimeout(timeoutId)
        timeoutId = null
      }
      lastCall = now
      fn(...args)
    }
    else if (!timeoutId && trailing) {
      timeoutId = setTimeout(() => {
        lastCall = Date.now()
        timeoutId = null
        fn(...args)
      }, remaining)
    }
  }
}

export const copyText = (text: string) => {
  try {
    navigator?.clipboard?.writeText(text)
    copyToClipboard(text)
    return true
  }
  catch (e) {
    console.log(e)
    return false
  }
}
